/**
 * Copyright (c) [2022] LiuGang(libbylg@126.com)
 * TinyEditor is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *             http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#ifndef VM_H
#define VM_H

#include <cstdint>

struct vm_inst_t {
    uint8_t opcode;
    uint8_t target : 4;
    uint8_t source : 4;
    int16_t offset;
    int32_t immval;
};

enum vm_reg : uint8_t {
    VM_REG_0 = 0x00,    //  返回值寄存器
    VM_REG_1 = 0x01,    //  通用寄存器
    VM_REG_2 = 0x02,    //  通用寄存器
    VM_REG_3 = 0x03,    //  通用寄存器
    VM_REG_4 = 0x04,    //  通用寄存器
    VM_REG_5 = 0x05,    //  通用寄存器
    VM_REG_6 = 0x06,    //  ??
    VM_REG_7 = 0x07,    //  ??
    VM_REG_8 = 0x08,    //  ??
    VM_REG_9 = 0x09,    //  ??
    VM_REG_A = 0x0A,    //  栈寄存器
    VM_REG_COUNT,
};

#define VM_REG_CALL_NUM (4)
#define VM_REG_CALL_BEGIN (VM_REG_6)
#define VM_REG_RET (VM_REG_0)
#define VM_REG_SP (VM_REG_A)

enum vm_inst_class : uint8_t {
    VM_CLS_MEM = 0x00, // 内存数据读写
    VM_CLS_ALU = 0x10, // 整数算数运算
    VM_CLS_BIT = 0x20, // 整数位运算
    VM_CLS_FPU = 0x30, // 浮点计算
    VM_CLS_REX = 0x40, // 寄存器间数据交换
    VM_CLS_CST = 0x50, // 数据转换运算
    VM_CLS_JMP = 0x60, // 跳转指令
    VM_CLS_JBC = 0x70, // 基于整数比较的跳转指令
};

enum vm_opcode : uint8_t {
#define VM_OP_DEF(arg_name, arg_id, arg_asmtmpl) arg_name = (arg_id),
#include "vm_opcode.h" //

#undef VM_OP_DEF
};

// clang-format off
struct vm_t;
extern  vm_t*   vm_create();
extern  void    vm_destroy(vm_t* vm);
extern  void    vm_load(vm_t* vm, const vm_inst_t* insts, uint32_t insts_num);
extern  int     vm_exec(vm_t* vm, void* memory, uint32_t size, uint64_t* retval);
// clang-format on



#endif // VM_H
